//
// Created by hsj on 2024-1-12.
// 多播基于UDP;多播组是D类IP地址( 224.0.0.0~ -239.255.255.255 )
// D类地址224.x.x.x~239.x.x.x
// 编译:  gcc multicast_recevier_win.c -LH:\mingw\mingw64\x86_64-w64-mingw32\lib -lws2_32 -o multicast_recevier_win
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>

#ifdef WIN32
//windows minGW64
//inet_pton函数：_WIN32_WINNT
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600
#include <winsock2.h>
#include <ws2tcpip.h>
//#pragma comment(lib,"ws2_32.lib")
#else
//linux  gcc
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#endif
#define BUF_SIZE 30
void ErrorHandling(char *buf);
int main(int argc,char *argv[]){
    WSADATA wsaData;
    SOCKET hRecvSock;
    SOCKADDR_IN adr;
    struct ip_mreq joinAdr;
    char buf[BUF_SIZE];
    int strLen;
    char ip[]="224.1.1.2";
    char port[]="1188";

    if(WSAStartup(MAKEWORD(2, 2),&wsaData)!=0)
        ErrorHandling( "WSAStartup() error !");

    hRecvSock=socket(PF_INET, SOCK_DGRAM, 0);
    memset(&adr, 0, sizeof(adr));
    adr.sin_family=AF_INET;
    adr.sin_addr.s_addr=htonl(INADDR_ANY);
    adr.sin_port=htons(atoi(/*argv[2]*/port));

    if(bind(hRecvSock, (SOCKADDR*) &adr, sizeof( adr))==SOCKET_ERROR)
        ErrorHandling("bind() error");

    joinAdr.imr_multiaddr.s_addr=inet_addr(/*argv[1]*/ip);//多播组IP
    joinAdr.imr_interface.s_addr=htonl(INADDR_ANY);//本机IP
    if(setsockopt(hRecvSock, IPPROTO_IP, IP_ADD_MEMBERSHIP,(void* )&joinAdr, sizeof(joinAdr) )==SOCKET_ERROR)
        ErrorHandling("setsock() error");

    while(1){
        strLen=recvfrom(hRecvSock, buf, BUF_SIZE - 1, 0, NULL, 0);//区别UDP
        if(strLen<0)
            break;
        buf[strLen]=0;
        printf("%s\n",buf);
    }
    closesocket (hRecvSock) ;
    WSACleanup();

    return EXIT_SUCCESS;
}

void ErrorHandling( char *message){
    fputs (message, stderr);
    fputc('\n', stderr);
    exit(1);
}

